// internal/socketIO/io.go
package socketIO

import (
	"fmt"
	"im/internal/common"
	"im/internal/model"
	"net/http"
	"time"

	"github.com/zishang520/socket.io/servers/socket/v3"
)

var Io *socket.Server

// UseMap 每个用户可以用多个SocketId
var UseMap = make(map[int]map[socket.SocketId]struct{})

type Message struct {
	ID       string `json:"id"`
	SendID   string `json:"sendID"`
	RecvID   string `json:"recvID"`
	GroupID  string `json:"groupID,omitempty"`
	Content  string `json:"content"`
	MsgType  int32  `json:"msgType"` // 消息类型: 100(文本), 101(图片), 102(语音)等
	SendTime int64  `json:"sendTime"`
	Extra    string `json:"extra,omitempty"`
}

type UserOnlineStatus struct {
	UserID   int         `json:"user_id"`
	Status   int32       `json:"status"` // 1:在线, 0:离线
	Platform string      `json:"platform"`
	UserInfo *model.User `json:"user_info"`
}

func Init(host string, port int) {
	Io = socket.NewServer(nil, nil)
	http.Handle("/socket.io/", Io.ServeHandler(nil))
	go http.ListenAndServe(fmt.Sprintf("%s:%d", host, port), nil)
	Io.On("connection", onConnection)
}

func onConnection(clients ...any) {
	skt := clients[0].(*socket.Socket)
	auth := skt.Handshake().Auth
	token, _ := auth["token"].(string)
	platform, _ := auth["platform"].(string)
	user, err := ComputeUserFromHeaders(token)
	if err != nil {
		skt.Emit("error", map[string]interface{}{
			"errCode": 401,
			"errMsg":  "用户认证失败",
		})
		return
	}

	// 用户加入房间
	userRoom := socket.Room(fmt.Sprintf("user_%d", user.Id))
	skt.Join(userRoom)
	if UseMap[user.Id] == nil {
		UseMap[user.Id] = make(map[socket.SocketId]struct{})
	}
	UseMap[user.Id][skt.Id()] = struct{}{}
	fmt.Println(fmt.Sprintf("用户上线通知: user_%d:%s", user.Id, user.Username))
	fmt.Println("当前在线用户数量:", len(UseMap))

	// 发送连接成功消息
	skt.Emit("connect_success", map[string]interface{}{
		"userID":     user.Id,
		"serverTime": time.Now().Unix(),
	})

	// 广播用户上线
	Io.Emit("user_status_change", UserOnlineStatus{
		UserID:   user.Id,
		Status:   1, // 在线
		Platform: platform,
		UserInfo: user,
	})
	//接受消息
	skt.On("message", func(data ...any) {
		fmt.Println("接收到消息:", data)
	})

	skt.On("disconnect", func(...any) {
		skt.Leave(userRoom)
		delete(UseMap[user.Id], skt.Id())
		//当用户没有Socket连接时，通知下线
		if len(UseMap[user.Id]) == 0 {
			delete(UseMap, user.Id)
			fmt.Println(fmt.Sprintf("用户下线通知: user_%d:%s", user.Id, user.Username))
			fmt.Println("当前在线用户数量:", len(UseMap))
			//下线通知
			Io.Emit("user_status_change", UserOnlineStatus{
				UserID:   user.Id,
				Status:   0, // 下线
				Platform: platform,
			})
		}
	})
}

func ComputeUserFromHeaders(token string) (*model.User, error) {
	return common.GetUserByToken(token)
}
